//
//  IMCert.h
//  IMSecurity
//
//  Created by infosec2013 on 16/5/24.
//  Copyright © 2016年 Infosec. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "IMUser.h"
typedef NS_ENUM(NSInteger,IMHashType) {
    IMHashTypeSM3,
    IMHashTypeMD5,
    IMHashTypeSHA1,
    IMHashTypeSHA256,
    IMHashTypeSHA512,
    IMHashTypeDefault //默认hash类型，根据证书签发使用的hash算法来确定
};

typedef  NS_ENUM(NSInteger,SignMode)
{
    SignModeRaw = 0,
    SignModeAttached,
    SignModeDetached
};


typedef NS_ENUM(NSInteger,CertItemType){
    CertItemTypeDN = 0, //证书DN
    CertItemTypeSN,     //证书SN
    CertItemTypeIsser,  //证书颁发者
    CertItemTypeKeyUsage = 4, //证书密钥用途
    CertItemTypeKeyLength,//证书密钥长度
    CertItemTypeNotBefore,//证书生效日期
    CertItemTypeNotAfter,//证书失效日期
    CertItemTypeAlg,    //证书签名算法
    CertItemTypeVersion, //证书版本
    CertItemTypePublicKey, //证书公钥
    CertItemTypeCertContent,//证书内容
};

@interface IMCert : NSObject
@property(nonatomic,readonly)NSString *username;

+ (instancetype)certWithUsername:(NSString *)username error:(int *)error;

- (void)generateP10WithPIN:(NSString *)PIN
             completeBlock:(void(^)(int resultCode,NSString *P10))completeBlock;

#pragma mark 证书管理和签名
/**
 证书申请
 
 @param PIN 证书PIN码
 @param completeBlock 完成后执行block
 */
- (void)applyCertWithPIN:(NSString *)PIN
           completeBlock:(void(^)(int resultCode))completeBlock;

/**
 更新证书
 
 @param PIN 当前证书PIN码
 @param newPIN 新证书PIN码
 @param completeBlock 完成后执行block
 */
- (void)updateCertWithPIN:(NSString *)PIN
                   newPIN:(NSString *)newPIN
         andCompleteBlock:(void(^)(int resultCode))completeBlock;

/**
 获取证书状态
 
 @param completeBlock 完成后执行代码块
        key：
            userstate:用户状态
            certstate：证书当前在线状态
            certnotafter：证书有效期
 */
- (void)getCertStateWithCompleteBlock:(void(^)(int resultCode,NSDictionary * dictState))completeBlock;


/**
 获取证书信息
 
 @param itemType 证书项名称:
 证书DN: "CERT_DN"
 证书SN:" "CERT_SN"
 证书颁发者：""CERT_ISSUER"
 证书状态:""CERT_STATUS"
 证书key用途："CERT_Key_USAGE"
 证书key长度: "CERT_KEY_LENGTH"
 证书生效日期:" "CERT_NOTBEFORE"
 证书失效日期：""CERT_NOTAFTER"
 证书签名算法：""CERT_ALG"
 证书版本:" "CERT_VERSION"
 @return 证书信息项内容，获取失败返回""
 */
- (NSString *)getCertInfoWithItem:(CertItemType)itemType;

- (NSString *)getEncCertificate;

+ (NSString *)getPublickKeyFromCert:(NSString *)cert;
/**
 二维码登录
 
 @param PIN 证书PIN码
 @param QRString QRCode扫描结果
 @param mode 二维码登录签名组包模式 raw attached detached
 @param completeBlock 完成后执行block
 */
- (void)loginByQRCodeWithPIN:(NSString *)PIN
                    QRString:(NSString *)QRString
                        mode:(SignMode)mode
            andCompleteBlock:(void(^)(int resultCode))completeBlock;

/**
*  修改PIN码
*
*  @param oldPIN 证书原始PIN
*  @param newPIN 证书新PIN
*
*/
- (void)changePINWithOldPIN:(NSString *)oldPIN
                  andNewPIN:(NSString *)newPIN
           andCompleteBlock:(void(^)(int resultCode,int remaintimes))completeBlock;

/**
 摘要签名
 
 @param algType 算法类型
 @param PIN 证书PIN码
 @param data 原文的摘要数据
 */
- (void)signWithoutIDWithAlg:(CertAlgType)algType
                         PIN:(NSString *)PIN
                        data:(NSData *)data
            andCompleteBlock:(void(^)(int resultCode,NSString *signResult))completeBlock;

/**
 对字符串进行签名

 @param PIN  证书PIN码
 @param plain 原文
 @param encoding 编码格式
 @param hashType 摘要算法类型 :    IMHashTypeSM3,  IMHashTypeMD5, IMHashTypeSHA1, IMHashTypeSHA256
 @param mode 签名组包模式      raw : 0 attached: 1 detached: 2
 */
- (void)signWithPIN:(NSString *)PIN
              Plain:(NSString *)plain
           encoding:(NSStringEncoding)encoding
           hashType:(IMHashType)hashType
               mode:(SignMode)mode
   andCompleteBlock:(void(^)(int resultCode,NSString *signResult))completeBlock;

/**
 对字节进行签名
 
 @param PIN  证书PIN码
 @param data  待签名数据
 @param hashType 摘要算法类型 :摘要算法类型 :    IMHashTypeSM3,  IMHashTypeMD5, IMHashTypeSHA1, IMHashTypeSHA256
 @param mode 签名组包模式      raw : 0 attached: 1 detached: 2
 */
- (void)signWithPIN:(NSString *)PIN
               data:(NSData *)data
               hashType:(IMHashType)hashType
               mode:(SignMode)mode
   andCompleteBlock:(void(^)(int resultCode,NSString *signResult))completeBlock;

/**
 验证PIN码
 
 @param PIN 用户证书PIN码
 @param completeBlock 完成后执行block resultCode: 返回码 0 成功 其他 失败   remaintimes: 剩余尝试次数
 */
- (void)verifyPIN:(NSString *)PIN andCompleteBlock:(void(^)(int ret,int remaintimes))completeBlock;

/**
 在线验签名
 
 @param plainData 原文
 @param signedData 签名结果
 @param cert 证书内容
 @param mode 签名组包模式
 @param completeBlock 完成后执行代码块
 */
- (void)verifySignDataWithPlainData:(NSString *)plainData
                         signedData:(NSString *)signedData
                               Cert:(NSString *)cert
                           signMode:(SignMode)mode
                   andCompleteBlock:(void(^)(int resultCode))completeBlock;


/// 本地验签名
/// @param plainData 签名原文
/// @param signedData 签名结果
/// @param cert 证书内容
/// @param hashType 摘要算法类型: IMHashTypeSM3,  IMHashTypeMD5, IMHashTypeSHA1, IMHashTypeSHA256
/// @param mode 签名组包模式
- (int)verifySignDataWithPlainData:(NSString *)plainData
                        signedData:(NSString *)signedData
                              Cert:(NSString *)cert
                          hashType:(IMHashType)hashType
                          signMode:(SignMode)mode;

/**
 *  获取剩余尝试次数
 *
 *  @return 次数
 */
- (int)getVerifyTimes;

/**
 是否含有某个用户的证书
 
 @param username 用户名
 @return 存在：YES 不存在：NO
 */
+ (BOOL)hasCertWithUsername:(NSString *)username;

/// 本地删除当前用户证书
- (BOOL)deleteCert;


/// 使用用户加密证书解密数据
/// @param strPIN 用户加密证书PIN码
/// @param cipherData 密文数据内容
/// @param completeBlock 完成后执行block
- (void)decryptWithPIN:(NSString *)strPIN cipherData:(NSData *)cipherData andCompleteBlock:(void(^)(int resultCode,NSData *plain))completeBlock;


/// 使用外部证书进行SM2加密
/// @param cert 公钥证书
/// @param data 待计算的数据
/// @param result 返回数据
/// @param resultLen 返回数据长度
+ (int)sm2EncryptWithCert:(NSString *)cert
                     data:(NSData *)data
                   result:(unsigned char *)result
                resultLen:(int *)resultLen;

/// 使用外部证书进行RSA加密
/// @param cert 公钥证书
/// @param data 待计算的数据
/// @param result 返回数据
/// @param resultLen 返回数据长度
+ (int)rsaEncryptWithCert:(NSString *)cert
                     data:(NSData *)data
                   result:(unsigned char *)result
                resultLen:(int *)resultLen;
/**
 制作数字信封

 @param strCipherName 加密算法（"des"/"des3"/"aes-256-ecb"/"aes-256-cbc"/"rc2"/"rc4"/"sms4-cbc"）
 @param plain 原文
 @return 数字信封
 */
- (NSString *)makeEnvelopeWithCert:(NSString *)cert cipherName:(NSString *)strCipherName plain:(NSData *)plain;


/**
 使用本地加密证书打开信封

 @param strPIN PIN
 @param strEnvelope 数字信封内容
 @param completeBlock 完成后执行block返回结果：resultCode 0 成功 其他失败  plain:信封内原文
 */
- (void)openEnvelopeWithPIN:(NSString *)strPIN envelop:(NSString *)strEnvelope andCompleteBlock:(void(^)(int resultCode,NSData *plain))completeBlock;
@end
